Author: Jorge Maldonado Ventura
Category: Web development
Date: 2017-09-16 13:38
Image: <img src="/wp-content/uploads/2017/09/menu-navegación-Bootstrap.png" alt="Example of Bootstrap navigation bar">
Lang: en
Modified: 2017-09-22 11:42
Slug: barra-de-navegacion-de-bootstrap-sin-javascript
Tags: advice, Bootstrap, CSS, HTML, JavaScript, jQuery
Title: Bootstrap navigation bar without JavaScript

[Bootstrap](https://github.com/twbs/bootstrap) is distributed with a JavaScript
file called `bootstrap.js` which requires
[jQuery](https://es.wikipedia.org/wiki/JQuery). This file allows, among other
things, making the navigation bar work when there are dropdown menus, and
toggle the navigation links, which are hidden in low-resolution screens.

The problem is that Bootstrap doesn't offer the same basic functionality without JavaScript.
Namely, if you don't have JavaScript enabled, you cannot access the dropdown
menu nor toggle the navigation menu in mobile or low-resolution devices. However,
it's possible to offer this features without JavaScritp. In this article I show
you how to do it.

<!-- more -->

First, we are going to create a navigation bar which works with JavaScript.
Remember to make sure that the path of the JavaScript and <abbr title="Cascading Style Sheets">CSS</abbr>
files is correct; you can download them and save them in the `css` and `js`
folders in the same directory where the <abbr title="HyperText Markup Language">HTML</abbr>
file is found. The version of Bootstrap used is the 3.3.7.

    ::html
    <!DOCTYPE html>
    <html lang="es">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width">
        <title>With JavaScript | Bootstrap navigation bar</title>
        <link rel="stylesheet" href="css/bootstrap.css" type="text/css">
        <script src="/theme/js/jquery-3.1.1.min.js"></script>
        <script src="js/bootstrap.js"></script>
      </head>
      <body>
        <nav class="navbar navbar-default navbar-fixed-top">
          <div class="container">
            <div class="navbar-header">
              <a href="/" class="navbar-brand">Freak Spot</a>
              <button aria-expanded="false" class="navbar-toggle" type="button" data-toggle="collapse" data-target="#navbar-main">
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
              </button>
            </div>
            <div class="navbar-collapse collapse" id="navbar-main">
              <ul class="nav navbar-nav">
                <li>
                  <a href="#">Another section</a>
                </li>
                <li>
                  <a href="https://es.wikipedia.org/wiki/Wikipedia:Portada">Wikipedia</a>
                </li>
                <li class="dropdown">
                  <a class="dropdown-toggle" data-toggle="dropdown" href="#" id="themes">Free Software <span class="caret"></span></a>
                  <ul class="dropdown-menu" aria-labelledby="themes">
                    <li><a href="https://www.fsf.org/">FSF</a></li>
                    <li><a href="https://www.gnu.org/">GNU</a></li>
                    <li><a href="https://peers.community/">Peers Community</a></li>
                  </ul>
                </li>
              </ul>
            </div>
          </div>
        </nav>
      </body>
    </html>

You can [find out how this example works](/wp-content/uploads/2017/09/barra-navegacion-Bootstrap.en/with-javascript.html). When you press on the togglable menu called "Free Software",
other options appear below; when the resolution is small, you just have to press
a button to toggle the navigation menu. But these two functionalities don't work
when JavaScript is disabled.

The changes we must do are the following, the removed lines start with `-` and
the new ones with `+`, (output obtained with the command `diff -u with-javascript.html
without-javascript.html`):

    ::diff
    --- with-javascript.html	2017-09-16 15:02:54.167637691 +0200
    +++ without-javascript.html	2017-09-22 11:32:11.008899729 +0200
    @@ -3,21 +3,37 @@
       <head>
         <meta charset="UTF-8">
         <meta name="viewport" content="width=device-width">
    -    <title>With JavaScript | Bootstrap navigation bar</title>
    +    <title>Without JavaScript | Barra de navegación de Bootstrap</title>
         <link rel="stylesheet" href="css/bootstrap.css" type="text/css">
    -    <script src="/theme/js/jquery-3.1.1.min.js"></script>
    -    <script src="js/bootstrap.js"></script>
    +    <style>
    +      .dropdown:hover > .dropdown-menu {
    +        display: block;
    +      }
    +
    +      label[for=navbar-toggle-cbox] {
    +        cursor: pointer;
    +      }
    +
    +      #navbar-toggle-cbox:checked ~ .collapse {
    +        display: block;
    +      }
    +
    +      #navbar-toggle-cbox {
    +        display: none;
    +      }
    +    </style>
       </head>
       <body>
         <nav class="navbar navbar-default navbar-fixed-top">
           <div class="container">
    +        <input aria-controls="navbar-main" id="navbar-toggle-cbox" role="button" type="checkbox">
             <div class="navbar-header">
               <a href="/" class="navbar-brand">Freak Spot</a>
    -          <button aria-expanded="false" class="navbar-toggle" type="button" data-toggle="collapse" data-target="#navbar-main">
    +          <label class="navbar-toggle collapsed" for="navbar-toggle-cbox">
                 <span class="icon-bar"></span>
                 <span class="icon-bar"></span>
                 <span class="icon-bar"></span>
    -          </button>
    +          </label>
             </div>
             <div class="navbar-collapse collapse" id="navbar-main">
               <ul class="nav navbar-nav">

The complete source code is shown below.

    ::html
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width">
        <title>Without JavaScript | Barra de navegación de Bootstrap</title>
        <link rel="stylesheet" href="css/bootstrap.css" type="text/css">
        <style>
          .dropdown:hover > .dropdown-menu {
            display: block;
          }

          label[for=navbar-toggle-cbox] {
            cursor: pointer;
          }

          #navbar-toggle-cbox:checked ~ .collapse {
            display: block;
          }

          #navbar-toggle-cbox {
            display: none;
          }
        </style>
      </head>
      <body>
        <nav class="navbar navbar-default navbar-fixed-top">
          <div class="container">
            <input aria-controls="navbar-main" id="navbar-toggle-cbox" role="button" type="checkbox">
            <div class="navbar-header">
              <a href="/" class="navbar-brand">Freak Spot</a>
              <label class="navbar-toggle collapsed" for="navbar-toggle-cbox">
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
              </label>
            </div>
            <div class="navbar-collapse collapse" id="navbar-main">
              <ul class="nav navbar-nav">
                <li>
                  <a href="#">Another Section</a>
                </li>
                <li>
                  <a href="https://en.wikipedia.org/wiki/Main_Page">Wikipedia</a>
                </li>
                <li class="dropdown">
                  <a class="dropdown-toggle" data-toggle="dropdown" href="#" id="themes">Free Software <span class="caret"></span></a>
                  <ul class="dropdown-menu" aria-labelledby="themes">
                    <li><a href="https://www.fsf.org/">FSF</a></li>
                    <li><a href="https://www.gnu.org/">GNU</a></li>
                    <li><a href="https://peers.community/">Peers Community</a></li>
                  </ul>
                </li>
              </ul>
            </div>
          </div>
        </nav>
      </body>
    </html>

You can [find out how this example works](/wp-content/uploads/2017/09/barra-navegacion-Bootstrap.en/without-javascript.html).
Now, pressing on "Free Software" is not necessary, you can simply hover it with
the mouse. The button for toggling the links in smaller resolution has been
replaced in the version without JavaScript with a hidden checkbox. The checkbox
is activated pressing the `<label>` element that is associated with it
(`for="navbar-toggle-cbox"`). When the checkbox is active, the links of the
navigation menu are shown with <abbr title="Cascading Style Sheets">CSS</abbr>
(`display: block`).

Unlike the JavaScript version, the version without JavaScript doesn't
have an animation when you toggle the navigation menu. It's impossible
to change the value of the attribute `aria-expanded` (which should
change to `true` when the menu is shown), so it must be removed.
Furthermore, maybe it's not enough to use the pseudoelement `:hover`.
In my opinion, the best thing is to avoid using a dropdown menu in the
navigation bar.

To sum up, if we are using other features offered by the file `bootstrap.js` or
we don't want to lose any functionality, there is no point in removing it.

What we must do to make it work for everyone[^1] is include the code
we added to the version without JavaScript inside the `<noscript>` tag,
so that the website works for people who enable JavaScript and people
who don't. To hide the button needed for the JavaScript version when
JavaScript is disabled, we can assign an `id` to the button and give it
the value `display: none`. The solution is shown below.

    ::html
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width">
        <title>With JavaScript and without JavaScript | Bootstrap navigation bar</title>
        <link rel="stylesheet" href="css/bootstrap.css" type="text/css">
        <script src="/theme/js/jquery-3.1.1.min.js"></script>
        <script src="js/bootstrap.js"></script>
        <style>
          #navbar-toggle-cbox {
            display: none;
          }
        </style>
        <noscript>
          <style>
            .dropdown:hover > .dropdown-menu {
              display: block;
            }

            label[for=navbar-toggle-cbox] {
              cursor: pointer;
            }

            #navbar-toggle-cbox:checked ~ .collapse {
              display: block;
            }

            #toggle-navbar {
              display: none;
            }
          </style>
        </noscript>
      </head>
      <body>
        <nav class="navbar navbar-default navbar-fixed-top">
          <div class="container">
            <input aria-controls="navbar-main" id="navbar-toggle-cbox" role="button" type="checkbox">
            <div class="navbar-header">
              <a href="/" class="navbar-brand">Freak Spot</a>
              <noscript>
                <label class="navbar-toggle" for="navbar-toggle-cbox">
                  <span class="icon-bar"></span>
                  <span class="icon-bar"></span>
                  <span class="icon-bar"></span>
                </label>
              </noscript>
              <button aria-expanded="false" class="navbar-toggle" id="toggle-navbar" type="button" data-toggle="collapse" data-target="#navbar-main">
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
              </button>
            </div>
            <div class="navbar-collapse collapse" id="navbar-main">
              <ul class="nav navbar-nav">
                <li>
                  <a href="#">Another Section</a>
                </li>
                <li>
                  <a href="https://en.wikipedia.org/wiki/Main_Page">Wikipedia</a>
                </li>
                <li class="dropdown">
                  <a class="dropdown-toggle" data-toggle="dropdown" href="#" id="themes">Free Software <span class="caret"></span></a>
                  <ul class="dropdown-menu" aria-labelledby="themes">
                    <li><a href="https://www.fsf.org/">FSF</a></li>
                    <li><a href="https://www.gnu.org/">GNU</a></li>
                    <li><a href="https://peers.community/">Peers Community</a></li>
                  </ul>
                </li>
              </ul>
            </div>
          </div>
        </nav>
      </body>
    </html>

You can [find out how this example works](/wp-content/uploads/2017/09/barra-navegacion-Bootstrap.en/with-and-without-js.html). The differences between the version with JavaScript and this solution are the following:

    ::diff
    --- with-javascript.html	2017-09-16 15:02:54.167637691 +0200
    +++ with-and-without-js.html	2017-09-22 11:32:31.276762097 +0200
    @@ -3,17 +3,49 @@
       <head>
         <meta charset="UTF-8">
         <meta name="viewport" content="width=device-width">
    -    <title>With JavaScript | Bootstrap navigation bar</title>
    +    <title>With JavaScript and without JavaScript | Bootstrap navigation bar</title>
         <link rel="stylesheet" href="css/bootstrap.css" type="text/css">
         <script src="/theme/js/jquery-3.1.1.min.js"></script>
         <script src="js/bootstrap.js"></script>
    +    <style>
    +      #navbar-toggle-cbox {
    +        display: none;
    +      }
    +    </style>
    +    <noscript>
    +      <style>
    +        .dropdown:hover > .dropdown-menu {
    +          display: block;
    +        }
    +
    +        label[for=navbar-toggle-cbox] {
    +          cursor: pointer;
    +        }
    +
    +        #navbar-toggle-cbox:checked ~ .collapse {
    +          display: block;
    +        }
    +
    +        #toggle-navbar {
    +          display: none;
    +        }
    +      </style>
    +    </noscript>
       </head>
       <body>
         <nav class="navbar navbar-default navbar-fixed-top">
           <div class="container">
    +        <input aria-controls="navbar-main" id="navbar-toggle-cbox" role="button" type="checkbox">
             <div class="navbar-header">
               <a href="/" class="navbar-brand">Freak Spot</a>
    -          <button aria-expanded="false" class="navbar-toggle" type="button" data-toggle="collapse" data-target="#navbar-main">
    +          <noscript>
    +            <label class="navbar-toggle" for="navbar-toggle-cbox">
    +              <span class="icon-bar"></span>
    +              <span class="icon-bar"></span>
    +              <span class="icon-bar"></span>
    +            </label>
    +          </noscript>
    +          <button aria-expanded="false" class="navbar-toggle" id="toggle-navbar" type="button" data-toggle="collapse" data-target="#navbar-main">
                 <span class="icon-bar"></span>
                 <span class="icon-bar"></span>
                 <span class="icon-bar"></span>

[^1]:
    Obviously, the ones who disable JavaScript will have less features, but
    the website will be usable.
